import sys
import os
import logging
from datetime import datetime
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from flask import Flask, jsonify, request, g
from flask_cors import CORS
from flask_jwt_extended import JWTManager
from app.models import db
from app.routes import auth_bp, users_bp, groups_bp, areas_bp, vehicles_bp, materials_bp, work_orders_bp, dashboard_bp
from app.routes.material_usage import material_usage_bp
from app.routes.dictionaries import dictionaries_bp
from app.routes.material_categories import material_categories_bp
from app.routes.form_templates import form_templates_bp
from app.routes.permissions import permissions_bp
from app.routes.system_configs import system_configs_bp
from dotenv import load_dotenv

load_dotenv()

def create_app():
    app = Flask(__name__, instance_relative_config=True)

    # ensure the instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass
    
    # 配置详细日志记录
    log_file = os.path.join(os.path.dirname(__file__), 'backend.log')
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        handlers=[
            logging.FileHandler(log_file, encoding='utf-8'),
            logging.StreamHandler()
        ]
    )
    
    # 创建专门的请求日志记录器
    request_logger = logging.getLogger('request_logger')
    request_logger.setLevel(logging.INFO)
    
    # 请求日志中间件
    @app.before_request
    def log_request_info():
        g.start_time = datetime.now()
        request_logger.info(f"[{request.method}] {request.url} - Origin: {request.headers.get('Origin', 'None')} - User-Agent: {request.headers.get('User-Agent', 'None')[:100]}")
        if request.method == 'OPTIONS':
            request_logger.info(f"CORS Preflight - Access-Control-Request-Method: {request.headers.get('Access-Control-Request-Method', 'None')}")
            request_logger.info(f"CORS Preflight - Access-Control-Request-Headers: {request.headers.get('Access-Control-Request-Headers', 'None')}")
        if request.is_json:
            try:
                data = request.get_json()
                if data:
                    # 不记录敏感信息如密码
                    data_copy = data.copy()
                    if 'password' in data_copy:
                        data_copy['password'] = '***'
                    request_logger.info(f"Request Body: {data_copy}")
            except Exception as e:
                request_logger.info(f"Failed to parse JSON: {e}")
    
    @app.after_request
    def log_response_info(response):
        duration = datetime.now() - g.start_time
        request_logger.info(f"Response: {response.status_code} - Duration: {duration.total_seconds():.3f}s")
        request_logger.info(f"Response Headers: Access-Control-Allow-Origin: {response.headers.get('Access-Control-Allow-Origin', 'None')}")
        request_logger.info(f"Response Headers: Access-Control-Allow-Methods: {response.headers.get('Access-Control-Allow-Methods', 'None')}")
        request_logger.info(f"Response Headers: Access-Control-Allow-Headers: {response.headers.get('Access-Control-Allow-Headers', 'None')}")
        return response
    
    # 配置
    app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev-secret-key')
    app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY', 'jwt-secret-key')
    app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///dispatch_system.db')
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    
    # 初始化扩展
    db.init_app(app)
    jwt = JWTManager(app)
    
    # 配置JWT - 确保兼容性
    app.config['JWT_IDENTITY_CLAIM'] = 'sub'
    app.config['JWT_ALGORITHM'] = 'HS256'
    
    # JWT错误处理
    @jwt.invalid_token_loader
    def invalid_token_callback(error):
        return jsonify({'error': 'Invalid token'}), 401
    
    @jwt.expired_token_loader
    def expired_token_callback(jwt_header, jwt_payload):
        return jsonify({'error': 'Token has expired'}), 401
    
    # 配置CORS，明确允许前端域名
    frontend_origins = os.getenv('CORS_ORIGINS', 'http://xin.xy506.cool:8173,http://localhost:8173,http://127.0.0.1:8173,http://192.168.1.99:8173,http://xin.xy506.cool:5000,http://localhost:5000,http://127.0.0.1:5000,http://192.168.1.99:5000').split(',')
    
    # 记录CORS配置
    app.logger.info(f"CORS配置 - 允许的源: {frontend_origins}")
    
    CORS(app, 
         resources={r"/api/*": {
             "origins": frontend_origins,
             "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
             "allow_headers": ["Content-Type", "Authorization", "X-Requested-With", "Accept", "Origin"],
             "expose_headers": ["Content-Type", "Authorization"],
             "supports_credentials": True,
             "send_wildcard": False,
             "automatic_options": True
         }}, 
         supports_credentials=True)
    
    # 添加手动CORS处理以确保所有OPTIONS请求都能正确响应
    @app.before_request
    def handle_preflight():
        if request.method == "OPTIONS":
            origin = request.headers.get('Origin')
            if origin in frontend_origins:
                response = jsonify({})
                response.headers.add("Access-Control-Allow-Origin", origin)
                response.headers.add('Access-Control-Allow-Headers', "Content-Type,Authorization,X-Requested-With,Accept,Origin")
                response.headers.add('Access-Control-Allow-Methods', "GET,PUT,POST,DELETE,OPTIONS,PATCH")
                response.headers.add('Access-Control-Allow-Credentials', 'true')
                app.logger.info(f"手动处理OPTIONS请求 - Origin: {origin}")
                return response
    
    # 注册蓝图
    app.register_blueprint(auth_bp, url_prefix='/api/auth')
    app.register_blueprint(users_bp, url_prefix='/api/users')
    app.register_blueprint(groups_bp, url_prefix='/api/groups')
    app.register_blueprint(areas_bp, url_prefix='/api/areas')
    app.register_blueprint(vehicles_bp, url_prefix='/api/vehicles')
    app.register_blueprint(materials_bp, url_prefix='/api/materials')
    app.register_blueprint(work_orders_bp, url_prefix='/api/work-orders')
    app.register_blueprint(material_usage_bp, url_prefix='/api/material-usage')
    app.register_blueprint(dashboard_bp, url_prefix='/api/dashboard')
    
    # 新增的管理API蓝图
    app.register_blueprint(dictionaries_bp, url_prefix='/api/dictionaries')
    # 为了兼容前端的两套API调用，同时注册system-dictionaries路由
    app.register_blueprint(dictionaries_bp, url_prefix='/api/system-dictionaries', name='system_dictionaries')
    app.register_blueprint(material_categories_bp, url_prefix='/api/material-categories')
    app.register_blueprint(form_templates_bp, url_prefix='/api/form-templates')
    app.register_blueprint(permissions_bp, url_prefix='/api/permissions')
    app.register_blueprint(system_configs_bp, url_prefix='/api/system-configs')



    @app.cli.command('init-db')
    def init_db_command():
        """Creates the database tables and populates them with test data."""
        with app.app_context():
            db.create_all()
        from app.models.user import User
        from app.models.group import Group
        from app.models.vehicle import Vehicle
        from app.models.material import Material

        if not User.query.filter_by(username='admin').first():
            print("Creating default admin user...")
            from datetime import date
            admin = User(
                username='admin',
                email='admin@example.com',
                role='admin',
                name='系统管理员',
                employee_id='ADMIN001',
                phone='00000000000',
                position='系统管理员',
                department='IT部',
                id_card='000000000000000000',
                ethnicity='汉族',
                gender='男',
                hire_date=date.today(),
                is_driver=False
            )
            admin.set_password('admin123')
            db.session.add(admin)
            db.session.commit()

        if not Group.query.first():
            print("Creating default groups...")
            group1 = Group(name='维修一组', description='负责A区域的维修任务')
            group2 = Group(name='维修二组', description='负责B区域的维修任务')
            db.session.add_all([group1, group2])
            db.session.commit()

        if User.query.count() <= 1:
            print("Creating default users...")
            from datetime import date
            group1 = Group.query.filter_by(name='维修一组').first()
            group2 = Group.query.filter_by(name='维修二组').first()
            user1 = User(
                username='manager1', email='manager1@example.com', role='manager', group_id=group1.id, 
                name='王经理', employee_id='M001', phone='13800138010', position='项目经理', department='维修部',
                id_card='110101199003070011', ethnicity='汉族', gender='男', hire_date=date.today(), is_driver=True
            )
            user1.set_password('password')
            user2 = User(
                username='user1', email='user1@example.com', role='user', group_id=group1.id, 
                name='张三', employee_id='E001', phone='13800138000', position='高级工程师', department='维修部',
                id_card='110101199203070012', ethnicity='汉族', gender='男', hire_date=date.today(), is_driver=False
            )
            user2.set_password('password')
            user3 = User(
                username='user2', email='user2@example.com', role='user', group_id=group2.id, 
                name='李四', employee_id='E002', phone='13800138001', position='初级工程师', department='维修部',
                id_card='110101199303070013', ethnicity='汉族', gender='男', hire_date=date.today(), is_driver=False
            )
            user3.set_password('password')
            db.session.add_all([user1, user2, user3])
            db.session.commit()



        if not Vehicle.query.first():
            print("Creating default vehicles...")
            group1 = Group.query.filter_by(name='维修一组').first()
            v1 = Vehicle(license_plate='京A88888', brand='福特', model='全顺', vehicle_type='工程车', group_id=group1.id)
            v2 = Vehicle(license_plate='京A66666', brand='金杯', model='海狮', vehicle_type='工具车', group_id=group1.id)
            db.session.add_all([v1, v2])
            db.session.commit()

        if not Material.query.first():
            print("Creating default materials...")
            m1 = Material(name='螺丝刀套装', code='M001', category='工具', stock_quantity=10, min_stock=2)
            m2 = Material(name='电缆', code='M002', category='耗材', stock_quantity=100, min_stock=20, unit='米')
            db.session.add_all([m1, m2])
            db.session.commit()
        print('Initialized the database.')

    return app

if __name__ == '__main__':
    app = create_app()
    app.run(debug=True, host='0.0.0.0', port=5000)
